//动态生成class文件

/*
  * param	            参数	            示例	                                        解释
    int version	        版本号	        V1_5	                                    1.5版本
    int access	        访问标志	        ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE	公有抽象接口
    String name	        类的全限定名称	“pkg/Comparable”	                        Comparable类名
    String signature	泛型签名	        null
    String superName	父类	            “java/lang/Object”	                        父类是Object
    String[] interfaces	接口	            new String[] { “pkg/Mesurable” }	        实现该接口
*
* */
import org.objectweb.asm.ClassWriter;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

import static org.objectweb.asm.Opcodes.*;
import asm.*;



public class AsmWriter{
    public static void main(String[] args) throws ClassNotFoundException {
        ClassWriter cw = new ClassWriter(0);
//        58|33|Stutem|null|java/lang/Object|[]
//        java版本号，类权限，类名，未知，继承父类，未知
        cw.visit(V1_8, ACC_PUBLIC, "HelloWorld",null,"java/lang/Object",null);
//        0|name|Ljava/lang/String;|null|null
//        字段的访问权限，字段的名字，字段的类型，未知，未知
        cw.visitField(ACC_PUBLIC,"name","I", null ,null);
//        方法的访问权限，方法的名称，方法的返回值类型，未知，未知
        cw.visitMethod(ACC_PUBLIC, "compareTo", "(Ljava/lang/Object;)V", null, null).visitEnd();
//        结束生成
        cw.visitEnd();
//        生成字节码数据
        byte[] b = cw.toByteArray();

        MyClassLoader my = new MyClassLoader();
        Class c = my.defineClass("HelloWorld",b);
        System.out.println(c.getMethods()[0].getName());

        writeFile("./out/production/asm/asm/CS.class",b);

//        CS cs = new CS();
//        cs.name = 1;
//        System.out.println(cs.name);
    }



    /**
     * 把数据流写入文件
     * @param path
     * @param bytes
     */
    static private void writeFile(String path, byte[] bytes) {
        try {
            FileOutputStream out = new FileOutputStream(path);//指定写到哪个路径中
            FileChannel fileChannel = out.getChannel();
            fileChannel.write(ByteBuffer.wrap(bytes)); //将字节流写入文件中
            fileChannel.force(true);//强制刷新
            fileChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
